package com.gimi.cloud.bbp.commonService.jiguang;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.ParseException;
import org.apache.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gimi.cloud.bbp.common.constant.RedisKeyConstant;
import com.gimi.cloud.bbp.common.utils.HttpClientUtil;
import com.gimi.cloud.bbp.common.utils.JsonUtil;
import com.gimi.cloud.bbp.commonService.jiguang.param.Audience;
import com.gimi.cloud.bbp.commonService.jiguang.param.JiguangPushParam;
import com.gimi.cloud.bbp.commonService.jiguang.param.Options;
import com.gimi.cloud.bbp.commonService.redis.RedisService;
import com.gimi.cloud.bbp.dao.dao.log.LogJPushDao;
import com.gimi.cloud.bbp.entity.log.LogJPush;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;

/**
 * 极光推送
 * @author zhoufuhang
 *
 */
//TODO zfh （需要测试IOS）
@Component
public class JiguangPushUtil {
	
	private final static Logger log = LoggerFactory.getLogger(JiguangPushUtil.class);

	private RedisService redisService;
	private LogJPushDao jPushDao;

	@Autowired
	public JiguangPushUtil(RedisService redisService, LogJPushDao jPushDao) {
		this.redisService = redisService;
		this.jPushDao = jPushDao;
	}
	/**
	 * 获取cid
	 * @param appKey
	 * @param masterSecret
	 * @return
	 * @throws Exception
	 */
	private String getCid(String cidUrl, String appKey, String masterSecret, Integer operatorId) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		map.put("Authorization", getAuthorization(appKey, masterSecret));
		String result = HttpClientUtil.sendGet(cidUrl, null, map, null);
		com.alibaba.fastjson.JSONObject resultObject = JsonUtil.jsonToJSONObject(result);
		//保存日志
		try {
			LogJPush logJPush = new LogJPush();
			logJPush.setPushSendType(3); //设置类型为获取CID
			logJPush.setPushResult(result);
			logJPush.setAddUid(operatorId);
			logJPush.setPushStatus(0); //设置为成功
			jPushDao.baseInsert(logJPush);
		} catch (Exception e) {
			log.error("极光推送信息保存异常：" + e.getMessage() , e);
		}
		return resultObject.getJSONArray("cidlist").getString(0);
	}
	
	/**
	 * 消息推送
	 * @param jsonParam
	 * @param appKey
	 * @param masterSecret
	 * @throws ParseException
	 * @throws IOException
	 */
	public String push(String url, String jsonParam, String appKey, String masterSecret, Integer operatorId) throws ParseException, IOException {
		BasicHeader basicHeader = new BasicHeader("Authorization", getAuthorization(appKey, masterSecret));
		List<Header> headerLists = new ArrayList<>();
		headerLists.add(basicHeader);
		String result = HttpClientUtil.sendPostJson(url, jsonParam, headerLists.toArray(new Header[headerLists.size()]));
		//添加日志
		try {
			LogJPush logJPush = new LogJPush();
			
			JSONObject paramObject = JSONObject.fromObject(jsonParam);
			logJPush.setPushSendType(1); //设置类型为全部推送
			if (paramObject.containsKey("audience")) {
				if (paramObject.getJSONObject("audience").containsKey("alias")) {
					logJPush.setPushSendPhone(paramObject.getJSONObject("audience").getString("alias"));
					logJPush.setPushSendType(2); //设置类型为别名推送
				}
			}
			logJPush.setPushStatus(0);
			JSONObject resultObject = JSONObject.fromObject(result);
			if (resultObject.containsKey("error")) {
				logJPush.setPushStatus(1);
			}
			logJPush.setPushParam(jsonParam);
			logJPush.setPushResult(result);
			logJPush.setAddUid(operatorId);
			jPushDao.baseInsert(logJPush);
		} catch (Exception e) {
			log.error("极光推送信息保存异常：" + e.getMessage() , e);
		}
		return result;
	}
	
	/**
	 * Authorization生成
	 * @param appKey
	 * @param masterSecret
	 * @return
	 */
	private static String getAuthorization(String appKey, String masterSecret) {
		return "Basic " + java.util.Base64.getEncoder().encodeToString((appKey + ":" + masterSecret).getBytes());
	}
	
	/**
	 * 推送消息给所有用户
	 * @param msg
	 * @param extras	附加字段
	 * @return
	 * @throws Exception
	 */
	public String pushAll(String msg, Map<String, Object> extras, Integer operatorId) throws Exception {
		com.alibaba.fastjson.JSONObject jsonConfig = redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_APP_JIGUANG_PUSH);
		log.info("redis配置" + jsonConfig.toString());
		//配置详情见：https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/
		JiguangPushParam jiguangPushParam = new JiguangPushParam();
		jiguangPushParam.setCid(getCid(jsonConfig.getString("cidUrl"), jsonConfig.getString("appKey"), jsonConfig.getString("masterSecret"), operatorId));
		jiguangPushParam.setAudience("all");
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("alert", msg);
		if (extras != null && !extras.isEmpty()) {
			JSONObject object = new JSONObject();
			object.put("extras", extras);
			jsonObject.put("android", object);
			jsonObject.put("ios", object);
		}
		jiguangPushParam.setNotification(jsonObject);
		
		Options options = new Options();
		options.setApns_production(jsonConfig.getBoolean("environment"));
		jiguangPushParam.setOptions(options);
		String pushParam = toJsonStr(jiguangPushParam);
		log.info("请求参数：" + pushParam);
		String resultStr = push(jsonConfig.getString("url"), pushParam, jsonConfig.getString("appKey"), jsonConfig.getString("masterSecret"), operatorId);
		log.info("返回值：" + resultStr);
		return resultStr;
	}
	
	/**
	 * 根据用户别名推送消息
	 * @param msg		推送文本
	 * @param extras	附加字段
	 * @param alias		用户别名
	 * @return
	 * @throws Exception
	 */
	public String pushAlias(String msg, Map<String, Object> extras, Integer operatorId, String... alias) throws Exception {
		com.alibaba.fastjson.JSONObject jsonConfig = redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_APP_JIGUANG_PUSH);
		log.info("redis配置" + jsonConfig.toString());
		//配置详情见：https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/
		JiguangPushParam jiguangPushParam = new JiguangPushParam();
		jiguangPushParam.setCid(getCid(jsonConfig.getString("cidUrl"), jsonConfig.getString("appKey"), jsonConfig.getString("masterSecret"), operatorId));
		
		Audience audience = new Audience();
		audience.setAlias(alias);
		
		jiguangPushParam.setAudience(audience);
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("alert", msg);
		if (extras != null && !extras.isEmpty()) {
			JSONObject object = new JSONObject();
			object.put("extras", extras);
			jsonObject.put("android", object);
			jsonObject.put("ios", object);
		}
		jiguangPushParam.setNotification(jsonObject);
		
		Options options = new Options();
		options.setApns_production(jsonConfig.getBoolean("environment"));
		jiguangPushParam.setOptions(options);
		
		String pushParam = toJsonStr(jiguangPushParam);
		log.info("请求参数：" + pushParam);
		String resultStr = push(jsonConfig.getString("url"), pushParam, jsonConfig.getString("appKey"), jsonConfig.getString("masterSecret"), operatorId);
		log.info("返回值：" + resultStr);
		return resultStr;
	}
	
	/**
	 * json序列化
	 * @param resp
	 * @return
	 */
	private static String toJsonStr(Object resp) {
		JsonConfig config = new JsonConfig();
		config.setJsonPropertyFilter((source, name, value) -> value == null);
		config.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {
			@Override  
			public Object processArrayValue(Object paramObject,  
			        JsonConfig paramJsonConfig) {  
			    return process(paramObject);  
			}  
			@Override  
			public Object processObjectValue(String paramString, Object paramObject,  
			        JsonConfig paramJsonConfig) {  
			    return process(paramObject);  
			}  
			private Object process(Object value){  
			    if(value instanceof Date){    
			        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA);    
			        return sdf.format(value);  
			    }    
			    return value == null ? "" : value.toString();    
			}  
		});
        String resultStr = JSONObject.fromObject(resp, config).toString();
        return resultStr;
	}
}
